package com.chujian.framework.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class JsonUs {

    private static final ObjectMapper javaObjectMapper = new ObjectMapper();
    private static JavaType javaObjectMapperType;
    private static final ObjectMapper normalObjectMapper = new ObjectMapper();

    static {
        initJavaObjectMapper();

        // normalObjectMapper 配置
        setJacksonTimeModule(normalObjectMapper);
        normalObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 包含java信息的 ObjectMapper
     *
     * @return
     */
    public static ObjectMapper javaObjectMapper() {
        return JsonUs.javaObjectMapper;
    }

    public static JavaType javaObjectMapperType() {
        return JsonUs.javaObjectMapperType;
    }

    /**
     * 返回一般的ObjectMapper
     *
     * @return
     */
    public static ObjectMapper objectMapper() {
        return normalObjectMapper;
    }

    private static void initJavaObjectMapper() {
        // 当str中的属性实体不存在时，忽略
        javaObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 指定要序列化的域，field,get和set,以及修饰符范围，ANY是都有包括private和public
        javaObjectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        setJacksonTimeModule(javaObjectMapper);

        // 携带JavaClass信息
        javaObjectMapper.activateDefaultTyping(javaObjectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        //
        javaObjectMapperType = TypeFactory.defaultInstance().constructType(Object.class);
    }

    // 解决jackson2无法反序列化LocalDateTime的问题
    private static void setJacksonTimeModule(ObjectMapper om) {
        om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        om.registerModule(new JavaTimeModule());
    }

    public static String toJsonStr(Object obj) {
        return toJacksonStr(obj);
    }

    public static String toJacksonStr(Object obj) {
        try {
            return normalObjectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * json字符串转为对象
     *
     * @param jsonStr
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T toObj(String jsonStr, Class<T> clazz) {
        try {
            return normalObjectMapper.readValue(jsonStr, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * json字符串转为List<对象>>
     *
     * @param jsonStr
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> toListObj(String jsonStr, Class<T> clazz) {
        JSONArray array = JSONObject.parseArray(jsonStr);
        List<T> rows = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj = array.getJSONObject(i);
            T row = obj.toJavaObject(clazz);
            rows.add(row);
        }
        return rows;
    }


    // 转为map
    public static Map<String, Object> toMap(String jsonStr) {
        if (StringUtils.isEmpty(jsonStr)) {
            return null;
        }
        return JSONObject.parseObject(jsonStr);
    }

}
